package com.pycredit.service.impl;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

import com.pycredit.bean.UserAnalyzerConfigParam;
import com.pycredit.bean.UserAnalyzerParam;
import com.pycredit.bean.UserAnalyzerResult;
import com.pycredit.config.UserModelConfig;
import com.pycredit.exception.BizException;
import com.pycredit.service.IUserAnalyzer;
import com.pycredit.util.DateUtil;
import com.pycredit.util.MathUtil;

public class UserAnalyzer implements IUserAnalyzer {

	public UserAnalyzerResult analyse(UserAnalyzerConfigParam userAnalyzerConfigParam, UserAnalyzerParam param)
			throws BizException {
		UserAnalyzerResult result = new UserAnalyzerResult();
		if (null == userAnalyzerConfigParam || param == null) {
			throw new BizException("UA-0002", "输入参数userAnalyzerConfigParam或param为空");
		}
		result.setIfRejected(!param.isHasSecurityAuth() || param.isBlacklistCorp());

		UserModelConfig config = UserModelConfig.getInstance();
		double[][] alpha = config.getUserModelAlpha();
		double[] beta = config.getUserModelBeta();
		Map<String, String[]> values = config.getValues();
		Map<String, String[]> xValues = config.getxValues();
		//占比重
		Double[] ratingWeight = userAnalyzerConfigParam.getRatingWeights();

		if (null == ratingWeight || ratingWeight.length != 2) {
			throw new BizException("UA-0002", "输入参数ratingWeight错误");
		}

		// 成立日期
		int monthInteval;
		try {
			monthInteval = DateUtil.getMonthInterval(param.getOpenDate(), new Date());
		} catch (IllegalAccessException e) {
			throw new BizException("UA-0003", e.getMessage());
		}
		String[] weightArr1 = getXValueByNumber(String.valueOf(monthInteval), "C1", values.get("C1"),
				xValues.get("C1"));
		// 企业人数
		String[] weightArr2 = getXValueByNumber(String.valueOf(param.getEmployeeCount()), "C2", values.get("C2"),
				xValues.get("C2"));
		// 行业排名
		String[] weightArr3 = getXValueByStr(String.valueOf(param.getTradeRank()), "C3", values.get("C3"),
				xValues.get("C3"));
		// 注册资金
		String[] weightArr4 = getXValueByNumber(String.valueOf(param.getRegistFund()), "C4", values.get("C4"),
				xValues.get("C4"));
		// 单位性质
		String[] weightArr5 = getXValueByStr(String.valueOf(param.getCorpType()), "C5", values.get("C5"),
				xValues.get("C5"));
		// 计划查询量
		String[] weightArr6 = getXValueByStr(String.valueOf(param.getSearchCount()), "C6", values.get("C6"),
				xValues.get("C6"));
		// 查询主要用途
		String[] weightArr7 = getXValueByStr(String.valueOf(param.getSearchReason()), "C7", values.get("C7"),
				xValues.get("C7"));
		// 信息查询类型
		String[] weightArr8 = getXValueBySpecile(String.valueOf(param.getSearchTypes()), "C8", values.get("C8"),
				xValues.get("C8"));
		String[] x = (String[]) concatAll(weightArr1, weightArr2, weightArr3, weightArr4, weightArr5, weightArr6,
				weightArr7, weightArr8);
		double fxSum = beta[0];

		double[] fx = new double[beta.length - 1];
		for (int i = 0; i < fx.length; i++) {
			double ax = alpha[0][i];
			for (int j = 0; j < x.length; j++) {
				ax = MathUtil.add(ax, MathUtil.mul(alpha[j + 1][i], Double.parseDouble(x[j])));
			}
			fx[i] = Math.tanh(ax);
			fxSum = MathUtil.add(fxSum, MathUtil.mul(beta[i + 1], fx[i]));
		}

		double y;
		try {
			y = MathUtil.div(1.0, MathUtil.add(1.0, Math.pow(Math.E, -fxSum)), 9);
		} catch (IllegalAccessException e) {
			throw new BizException("UA-0004", "系统计算错误：" + e.getMessage());
		}
		result.setModelValue(y);
		result.setExpertScore(param.getExpertRating());
		// 准入得分 = 模型结果*100*w1+专家给分*w2
		double score = MathUtil.add(MathUtil.mul(y, MathUtil.mul(100.0, ratingWeight[0])),
				MathUtil.mul(result.getExpertScore(), ratingWeight[1]));
		result.setScore(new BigDecimal(score).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
		result.setAdvise(getAdviseByScore(score));
		return result;

	}

	private String getAdviseByScore(double score) {
		if (score < 40) {
			return "建议不准入";
		} else if (score > 60) {
			return "建议准入";
		} else {
			return "建议进一步考察";
		}
	}

	private String[] getXValueByStr(String value, String type, String[] values, String[] xValues) throws BizException {

		int index = -1;

		for (int i = 0; i < values.length; i++) {
			if (values[i].trim().equals(value.trim())) {
				index = i;
				break;
			}
		}

		if (index == -1 && ("C5".equals(type) || "C7".equals(type))) {
			index = values.length - 1;
		}

		if (index == -1) {
			throw new BizException("UA-0002", "输入参数错误，没有找到相应的配置! 类型：<" + type + ">, 值: <" + value + ">.");
		}

		// 根据索引找到对应的xValues
		String xValue = xValues[index];
		String[] result = xValue.split(",");

		return result;
	}

	private String[] getXValueBySpecile(String value, String type, String[] values, String[] xValues)
			throws BizException {

		String resultStr = "";
		for (int i = 0; i < values.length; i++) {
			if (value.trim().contains(values[i].trim())) {
				if ("".equals(resultStr)) {
					resultStr = xValues[i];
				} else {
					resultStr = mulArrayStr(resultStr, xValues[i]);
				}
			}
		}

		if ("".equals(resultStr)) {
			throw new BizException("UA-0002", "输入参数错误，没有找到相应的配置! 类型：<" + type + ">, 值: <" + value + ">.");
		}

		String[] result = resultStr.split(",");

		return result;
	}

	private String[] getXValueByNumber(String value, String type, String[] values, String[] xValues)
			throws BizException {

		int index = -1;
		// 根据value 计算落在values 的哪个区间
		if ("C1".equals(type) || "C2".equals(type) || "C4".equals(type)) {
			for (int i = 0; i < values.length; i++) {
				if (i < values.length - 1 && Double.parseDouble(value) > Double.parseDouble(values[i])
						&& Double.parseDouble(value) <= Double.parseDouble(values[i + 1])) {
					index = i;
					break;
				} else if (i == values.length - 1 && Double.parseDouble(value) > Double.parseDouble(values[i])) {
					index = i;
					break;
				}
			}
		}

		if (index == -1) {
			throw new BizException("UA-0002", "输入参数错误，没有找到相应的配置! 类型：<" + type + ">, 值: <" + value + ">.");
		}

		// 根据索引找到对应的xValues
		String xValue = xValues[index];
		String[] result = xValue.split(",");

		return result;
	}

	public static <T> T[] concatAll(T[] first, T[]... rest) {
		int totalLength = first.length;
		for (T[] array : rest) {
			if (array != null) {
				totalLength += array.length;
			}
		}
		T[] result = Arrays.copyOf(first, totalLength);
		int offset = first.length;
		for (T[] array : rest) {
			if (array != null) {
				System.arraycopy(array, 0, result, offset, array.length);
				offset += array.length;
			}
		}
		return result;
	}

	/**
	 * 数字字符串向量相乘方法，字符数字以“，”分隔，个数一致
	 * @param value1 被乘数
	 * @param value2 乘数
	 * @return 乘积的字符串向量
	 * @throws BizException 
	 */
	public String mulArrayStr(String value1, String value2) throws BizException {
		String result = "";
		try {
			String[] value1Array = value1.split(",");
			String[] value2Array = value2.split(",");
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < value1Array.length; i++) {
				sb.append(MathUtil.mul(Double.valueOf(value1Array[i]), Double.valueOf(value2Array[i]))).append(",");
			}
			result = sb.toString().substring(0, sb.length() - 1);
		} catch (Exception e) {
			throw new BizException("UA-0005",
					"计算数字字符向量乘积错误! value1：<" + value1 + ">, value2: <" + value2 + ">." + e.getMessage());
		}
		return result;
	}
}
